<!DOCTYPE html>
<html lang="en">

<head>
    <title></title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="css/style.css" rel="stylesheet">
</head>

<body>
    <div style="display:none">
        <p class="p">123</p>
        <p class="p">123</p>
        <p class="p">123</p>
        <p>123</p>
        <p>123</p>
    </div>
</body>
<script>
    // let obj = { name: '张三' };
    // console.log(obj.__proto__);
    // //obj 的原型就是 [[Prototype]]: Object
    // let a = {};
    // let b = {};
    // console.log(Object.getPrototypeOf(a) == obj.__proto__);//true
    // console.log(Object.getPrototypeOf(a) == Object.getPrototypeOf(b));//true
    // 我们也可以创建一个极简对象（纯数据字典对象）没有原型（原型为 null)
    // let ay = { name: '软工' };
    // console.log(ay.hasOwnProperty('name'));//查询对象中是否有该属性
    // //创建出没有原型的对象
    // let gx = Object.create(null, {
    //     naem: {
    //         value: '计科'
    //     }
    // });
    // console.log(gx.hasOwnProperty('name'));//error
    // console.log(gx);//naem: "计科"
    // //原型关系网
    // //Object.prototype.__proto__ 为根节点
    // console.log(Object.prototype.__proto__);//null
    // Object.prototype.show = function () {
    //     alert("我是根节点");
    // };
    // //字符串 内部创建字符串 也是 new String('')
    // let str = '';
    // console.log(str.__proto__ == String.prototype);//true
    // console.log(str.__proto__.__proto__.show);//找到根节点
    // console.log(Object.prototype == String.prototype.__proto__);
    //字符串 内部创建字符串 也是 new Array('[]')
    // let arr = [];
    // console.log(arr.__proto__ == Array.prototype);//true
    // console.log(arr.__proto__.__proto__.show);//找到根节点
    // console.log(Object.prototype == Array.prototype.__proto__);
    // //字符串 内部创建字符串 也是 new Boolean('true)
    // let boolean = true;
    // console.log(boolean.__proto__ == Boolean.prototype);//true
    // console.log(boolean.__proto__.__proto__.show);//找到根节点
    // console.log(Object.prototype == Boolean.prototype.__proto__)

    // 1. __proto__是每个对象都有的一个属性，而prototype是函数才会有的属性。 2. __proto__指向的是 当前对象 的 原型对象 ，而prototype指向的，是以 当前函数 作为 构造函数 构造出来的 对象 的 原型对象 。
    // function User() { }
    // console.dir(User);
    // console.dir(User.__proto__);
    // console.dir(User.prototype);
    // // 使用 setPrototypeOf 与 getPrototypeOf 获取与设置原型
    // let sun = {};
    // let parent = { name: "parent" };
    // Object.setPrototypeOf(sun, parent); //第一个参数 是 被操作的对象 第二个是他的父辈
    // console.log(sun.__proto__);//{name: 'parent'}
    // console.log(Object.getPrototypeOf(sun));//{name: 'parent'} 获取当前对象的父元素
    // constructor 存在于 prototype 原型中，用于指向构建函数的引用。
    // function AY() {
    //     this.show = function () {
    //         return 'show AY';
    //     };
    // }
    // const obj = new AY();
    // console.log(obj instanceof AY);//true
    // const obj2 = new obj.constructor();
    // console.log(obj2.show() == obj.show());//true
    //使用对象的 constructor 创建对象
    // function User(name, age) {

    //     this.name = name;
    //     this.age = age;
    // }
    // function createByObject(obj, ...arg) {
    //     const constructor = Object.getPrototypeOf(obj).constructor;
    //     // console.log(Object.getPrototypeOf(obj).constructor);
    //     return new constructor(...arg);
    // }
    // let zs = new User('张三');
    // let ls = createByObject(zs, '李四', 12);
    // console.log(ls.constructor.prototype);
    //子集 可以通过constructor属性来找到他的父辈

    //dom数组借用 Array中的方法 过滤出来所有含calss的元素
    // let domp = document.querySelectorAll('p');
    //因为dom数组中没有过滤函数 而array中含有
    // domp = Array.prototype.filter.call(domp, (item => {
    //     // console.log(item);
    //     return item.hasAttribute('class');
    // }));
    // console.log(domp);//过滤出来所有含class的元素
    // domp = Array.prototype.map.call(domp, (item => {
    //     return item.hasAttribute('class');
    // }));
    // console.log(domp);//过滤出来所有含class的元素
    // var a = Array.prototype.map.call("Hello World", function (x) {
    //     return x.charCodeAt(0);
    // });
    // console.log(a)
    //构造函数
    // function User() {

    // }
    // function user() {

    // }
    // console.log(User.prototype == user.prototype);//构找函数不同函数不相等 false
    // console.dir(User.prototype);
    // console.dir(user.prototype)
    //对象工厂 通过对象工厂可以批量生成对象中的继承关系
    // function extend(sub, sup) {
    //     sub.prototype = Object.create(sup.prototype);
    //     sub.prototype.constructor = sub;
    // }
    // function Access() { }
    // function User() { }
    // function Admin() { }
    // function Member() { }
    // extend(User, Access);//User继承Access
    // extend(Admin, User); //Admin继承User
    // extend(Member, Access); //Member继承Access
    // Access.prototype.show = function () {
    //     console.log('Access 中的show');
    // };
    // User.prototype.show = function () {
    //     console.log('User show');
    // };
    // Member.prototype.member = function () {
    //     console.log('我是member');
    // };
    // new Admin().show();//因为 User是Admin的直接父辈就近原则调用user中的show
    // new Member().show();//找父辈中的show方法
    // console.dir(new Admin());
    // console.dir(new Member());

    //混合模式mixin 来实现多继承
    function extend(sub, sup) {
        sub.prototype = Object.create(sup.prototype);
        sub.prototype.constructor = sub;
    }
    const Request = {
        ajax() {
            return '获取请求';
        }
    };

    const Credit = {
        ___proto__: Request,//覆盖原来的__proto__属性 来继承Requirt对象中的方法
        total() {
            console.log(this.ajax() + '积分获取');
        }
    };
    //Credit.__proto__ = Request;

    function User(name, age) {

        this.name = name;
        this.age = age;
    }
    User.prototype.show = function () {
        console.log(this.name, this.age);
    };

    function Admin(...args) {
        User.apply(this, args);//因为user中用到this指针 所以需要用call来改变指针指向
        // console.log('构造函数');
    }
    extend(Admin, User);
    Object.assign(Admin.prototype, Request, Credit);//通过对象的属性合并 来实现方法的继承
    let obj = new Admin('张三', 15);
    obj.show();
    obj.total();
    console.log(obj.ajax())
</script>

</html>